<template>
	<div class="cascade-container">
		<div class="select-trigger" @click="togglePanel">
			<div class="selected-text">
				{{ selectedText }}
			</div>
			<div class="arrow" :class="{ 'is-reverse': isPanelVisible }">▼</div>
		</div>

		<div v-show="isPanelVisible" class="select-panel">
			<div class="panel-content">
				<div class="level-one">
					<div
						v-for="item in options"
						:key="item.id"
						:class="['level-one-item', { active: selectedLevel1 === item.id }]"
						@click="handleLevel1Select(item)">
						{{ item.name }}
					</div>
				</div>

				<div class="level-two" v-if="levelTwoData.length">
					<div
						v-for="item in levelTwoData"
						:key="item.id"
						:class="['level-two-item', { active: modelValue.includes(item.id) }]"
						@click="handleLevel2Select(item)">
						{{ item.name }}
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';

// 定义类型
interface Option {
	id: number;
	name: string;
	children?: Option[];
}

// 定义 props
const props = defineProps<{
	options: Option[]; // 级联选择器的选项数据
	modelValue: number[]; // v-model绑定值
	placeholder?: string; // 占位文本
}>();

// 定义 emits
const emit = defineEmits<{
	'update:modelValue': [value: number[]];
	change: [value: number[], items: Option[]];
}>();

// 状态管理
const isPanelVisible = ref(false);
const selectedLevel1 = ref<number>();
const levelTwoData = ref<Option[]>([]);

// 处理第一级选择
const handleLevel1Select = (item: Option) => {
	selectedLevel1.value = item.id;
	levelTwoData.value = item.children || [];
	emit('update:modelValue', []); // 清空二级选择
};

// 处理第二级选择
const handleLevel2Select = (item: Option) => {
	const newValue = [...props.modelValue];
	const index = newValue.indexOf(item.id);

	if (index === -1) {
		newValue.push(item.id);
	} else {
		newValue.splice(index, 1);
	}

	emit('update:modelValue', newValue);
	emit(
		'change',
		newValue,
		levelTwoData.value.filter((i) => newValue.includes(i.id))
	);
};

// 计算已选择的项目
const selectedItems = computed(() => {
	return levelTwoData.value.filter((item) => props.modelValue.includes(item.id));
});

// 计算显示文本
const selectedText = computed(() => {
	if (selectedItems.value.length === 0) {
		return props.placeholder || '请选择';
	}
	return selectedItems.value.map((item) => item.name).join('、');
});

// 切换面板显示状态
const togglePanel = () => {
	isPanelVisible.value = !isPanelVisible.value;
};

// 点击外部关闭面板
const handleClickOutside = (e: MouseEvent) => {
	const container = document.querySelector('.cascade-container');
	if (container && !container.contains(e.target as Node)) {
		isPanelVisible.value = false;
	}
};

// 生命周期钩子
onMounted(() => {
	document.addEventListener('click', handleClickOutside);
});

onUnmounted(() => {
	document.removeEventListener('click', handleClickOutside);
});
</script>

<style scoped lang="scss">
.cascade-container {
	width: 180px;
	position: relative;
}

.select-trigger {
	height: 32px;
	padding: 0 12px;
	border: 1px solid #d9d9d9;
	border-radius: 4px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	cursor: pointer;
	background: #fff;
	transition: all 0.3s;

	&:hover {
		border-color: #1890ff;
	}

	.selected-text {
		flex: 1;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
		color: #666;
	}

	.arrow {
		font-size: 12px;
		color: #999;
		transition: transform 0.3s;

		&.is-reverse {
			transform: rotate(180deg);
		}
	}
}

.select-panel {
	position: absolute;
	top: 100%;
	left: 0;
	width: 100%;
	margin-top: 4px;
	background: #fff;
	border: 1px solid #e8e8e8;
	border-radius: 4px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
	z-index: 1000;

	.panel-content {
		max-height: 300px;
		overflow-y: auto;
		padding: 12px;
	}
}

.level-one {
	border-bottom: 1px solid #f0f0f0;
	padding-bottom: 8px;
	margin-bottom: 8px;

	&-item {
		padding: 6px 12px;
		cursor: pointer;
		transition: all 0.3s;
		border-radius: 4px;

		&:hover {
			background-color: #f5f5f5;
		}

		&.active {
			color: #1890ff;
			background-color: #e6f7ff;
		}
	}
}

.level-two {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;

	&-item {
		padding: 4px 8px;
		border-radius: 4px;
		cursor: pointer;
		border: 1px solid #d9d9d9;
		font-size: 12px;
		transition: all 0.3s;

		&:hover {
			border-color: #1890ff;
			color: #1890ff;
		}

		&.active {
			background-color: #e6f7ff;
			border-color: #1890ff;
			color: #1890ff;
		}
	}
}
</style>
